/*******************************************************************************
* Copyright (c) 2015, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.ui.internal.e4.migration;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.internal.workbench.E4Workbench;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.Workbench;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.e4.compatibility.CompatibilityPart;
import org.eclipse.ui.internal.menus.MenuHelper;
import org.eclipse.ui.internal.registry.StickyViewDescriptor;
import org.eclipse.ui.internal.registry.ViewRegistry;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.views.IStickyViewDescriptor;
import org.eclipse.ui.views.IViewRegistry;
public class WorkbenchMigrationProcessor {
@Inject
private MApplication application;
@Inject
private IEclipseContext context;
@Inject
private EModelService modelService;
private IMemento workbenchMemento;
private File legacyWorkbenchFile;
private boolean migrated;
private List<MWindow> defaultWindows;
public boolean isLegacyWorkbenchDetected() {
legacyWorkbenchFile = getLegacyWorkbenchFile();
return legacyWorkbenchFile != null && legacyWorkbenchFile.exists();
}
public void migrate() {
if (!isLegacyWorkbenchDetected()) {
return;
}
workbenchMemento = loadMemento();
if (workbenchMemento == null) {
return;
}
defaultWindows = new ArrayList<>(application.getChildren());
application.getChildren().clear();
IEclipseContext builderContext = context.createChild();
IModelBuilderFactory builderFactory = ContextInjectionFactory.make(
ModelBuilderFactoryImpl.class, builderContext);
builderContext.set(IModelBuilderFactory.class, builderFactory);
ApplicationBuilder modelBuilder = builderFactory.createApplicationBuilder(new WorkbenchMementoReader(
workbenchMemento));
modelBuilder.createApplication();
context.remove(E4Workbench.NO_SAVED_MODEL_FOUND);
PrefUtil.getAPIPreferenceStore().setValue(IWorkbenchPreferenceConstants.SHOW_INTRO, false);
migrated = true;
}
private IMemento loadMemento() {
BufferedReader reader = null;
IMemento memento = null;
try {
reader = new BufferedReader(
new InputStreamReader(new FileInputStream(legacyWorkbenchFile), StandardCharsets.UTF_8));
memento = XMLMemento.createReadRoot(reader);
} catch (IOException e) {
WorkbenchPlugin.log("Failed to load " + legacyWorkbenchFile.getAbsolutePath(), e); //$NON-NLS-1$
} catch (WorkbenchException e) {
WorkbenchPlugin.log("Failed to load " + legacyWorkbenchFile.getAbsolutePath(), e); //$NON-NLS-1$
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
WorkbenchPlugin.log(e);
}
}
}
return memento;
}
private File getLegacyWorkbenchFile() {
if (legacyWorkbenchFile == null) {
IPath path = WorkbenchPlugin.getDefault().getDataLocation();
if (path == null) {
return null;
}
path = path.append(Workbench.DEFAULT_WORKBENCH_STATE_FILENAME);
legacyWorkbenchFile = path.toFile();
}
return legacyWorkbenchFile;
}
public boolean isWorkbenchMigrated() {
return migrated;
}
public void updatePartsAfterMigration(IPerspectiveRegistry perspectiveRegistry,
IViewRegistry viewRegistry) {
if (!migrated) {
return;
}
for (MPartDescriptor desc : application.getDescriptors()) {
for (MPart part : modelService.findElements(application, desc.getElementId(), MPart.class, null)) {
if (part.getLabel() == null) {
part.setLabel(desc.getLocalizedLabel());
}
if (part.getTooltip() == null) {
part.setTooltip(desc.getLocalizedTooltip());
}
if (part.getIconURI() == null) {
part.setIconURI(desc.getIconURI());
}
}
}
for (MPerspective persp : modelService.findElements(application, null, MPerspective.class, null)) {
setPerspectiveIcon(perspectiveRegistry, persp);
}
for (MUIElement snippet : application.getSnippets()) {
if (snippet instanceof MPerspective) {
setPerspectiveIcon(perspectiveRegistry, (MPerspective) snippet);
}
}
IStickyViewDescriptor[] stickyViews = viewRegistry.getStickyViews();
for (MWindow window : application.getChildren()) {
moveStickyViews(stickyViews, window);
}
}
private void moveStickyViews(IStickyViewDescriptor[] stickyViews, MWindow window) {
for (IStickyViewDescriptor stickyView : stickyViews) {
removeStickyViewFromPerspectives(stickyView, window);
}
for (MPartStack stickyFolder : modelService.findElements(application,
StickyViewDescriptor.STICKY_FOLDER_RIGHT, MPartStack.class, null)) {
fillStickyFolder(stickyViews, stickyFolder);
}
}
private void removeStickyViewFromPerspectives(IStickyViewDescriptor stickyView, MWindow window) {
for (MPlaceholder placeholder : modelService.findElements(window, stickyView.getId(),
MPlaceholder.class, null)) {
MElementContainer<MUIElement> parent = placeholder.getParent();
if (StickyViewDescriptor.STICKY_FOLDER_RIGHT.equals(parent.getElementId())) {
continue;
}
placeholder.setToBeRendered(false);
placeholder.setVisible(false);
parent.getChildren().remove(placeholder);
// remove empty container
if (parent.getChildren().isEmpty()) {
parent.getParent().getChildren().remove(parent);
} else if (parent.getSelectedElement() == placeholder) {
parent.setSelectedElement(null);
}
}
}
private void fillStickyFolder(IStickyViewDescriptor[] stickyViews, MPartStack stickyFolder) {
for (IStickyViewDescriptor stickyView : stickyViews) {
addPartToStickyFolder(stickyView.getId(), stickyFolder);
}
}
private void setPerspectiveIcon(IPerspectiveRegistry perspectiveRegistry, MPerspective perspective) {
String perspId = perspective.getElementId();
if (perspective.getTransientData().containsKey(PerspectiveBuilder.ORIGINAL_ID)) {
perspId = (String) perspective.getTransientData().get(PerspectiveBuilder.ORIGINAL_ID);
}
IPerspectiveDescriptor orgPerspDescr = perspectiveRegistry.findPerspectiveWithId(perspId);
if (orgPerspDescr != null) {
perspective.setIconURI(MenuHelper.getIconURI(orgPerspDescr.getImageDescriptor(), context));
}
}
private MPlaceholder addPartToStickyFolder(String partId, MPartStack stickyFolder) {
MPart part = null;
MWindow window = modelService.getTopLevelWindowFor(stickyFolder);
for (MUIElement element : window.getSharedElements()) {
if (element.getElementId().equals(partId)) {
part = (MPart) element;
break;
}
}
if (part == null) {
part = modelService.createModelElement(MPart.class);
part.setElementId(partId);
part.setContributionURI(CompatibilityPart.COMPATIBILITY_VIEW_URI);
part.getTags().add(ViewRegistry.VIEW_TAG);
window.getSharedElements().add(part);
}
MPlaceholder placeholder = null;
placeholder = modelService.createModelElement(MPlaceholder.class);
placeholder.setElementId(partId);
placeholder.setRef(part);
placeholder.setToBeRendered(false);
part.setCurSharedRef(placeholder);
stickyFolder.getChildren().add(placeholder);
return placeholder;
}
public void restoreDefaultModel() {
application.getTags().clear();
application.getPersistedState().clear();
application.getSnippets().clear();
application.getDescriptors().clear();
application.getChildren().clear();
application.getChildren().addAll(defaultWindows);
}
}